home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / perl5 / PPI / Node.pm < prev    next >
Encoding:
Perl POD Document  |  2010-07-06  |  20.0 KB  |  822 lines

  1. package PPI::Node;
  2.  
  3. =pod
  4.  
  5. =head1 NAME
  6.  
  7. PPI::Node - Abstract PPI Node class, an Element that can contain other Elements
  8.  
  9. =head1 INHERITANCE
  10.  
  11.   PPI::Node
  12.   isa PPI::Element
  13.  
  14. =head1 SYNOPSIS
  15.  
  16.   # Create a typical node (a Document in this case)
  17.   my $Node = PPI::Document->new;
  18.   
  19.   # Add an element to the node( in this case, a token )
  20.   my $Token = PPI::Token::Word->new('my');
  21.   $Node->add_element( $Token );
  22.   
  23.   # Get the elements for the Node
  24.   my @elements = $Node->children;
  25.   
  26.   # Find all the barewords within a Node
  27.   my $barewords = $Node->find( 'PPI::Token::Word' );
  28.   
  29.   # Find by more complex criteria
  30.   my $my_tokens = $Node->find( sub { $_[1]->content eq 'my' } );
  31.   
  32.   # Remove all the whitespace
  33.   $Node->prune( 'PPI::Token::Whitespace' );
  34.   
  35.   # Remove by more complex criteria
  36.   $Node->prune( sub { $_[1]->content eq 'my' } );
  37.  
  38. =head1 DESCRIPTION
  39.  
  40. The C<PPI::Node> class provides an abstract base class for the Element
  41. classes that are able to contain other elements L<PPI::Document>,
  42. L<PPI::Statement>, and L<PPI::Structure>.
  43.  
  44. As well as those listed below, all of the methods that apply to
  45. L<PPI::Element> objects also apply to C<PPI::Node> objects.
  46.  
  47. =head1 METHODS
  48.  
  49. =cut
  50.  
  51. use strict;
  52. use Carp            ();
  53. use Scalar::Util    qw{refaddr};
  54. use List::MoreUtils ();
  55. use Params::Util    qw{_INSTANCE _CLASS _CODELIKE};
  56. use PPI::Element    ();
  57.  
  58. use vars qw{$VERSION @ISA *_PARENT};
  59. BEGIN {
  60.     $VERSION = '1.213';
  61.     @ISA     = 'PPI::Element';
  62.     *_PARENT = *PPI::Element::_PARENT;
  63. }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. #####################################################################
  70. # The basic constructor
  71.  
  72. sub new {
  73.     my $class = ref $_[0] || $_[0];
  74.     bless { children => [] }, $class;
  75. }
  76.  
  77.  
  78.  
  79.  
  80.  
  81. #####################################################################
  82. # PDOM Methods
  83.  
  84. =pod
  85.  
  86. =head2 scope
  87.  
  88. The C<scope> method returns true if the node represents a lexical scope
  89. boundary, or false if it does not.
  90.  
  91. =cut
  92.  
  93. ### XS -> PPI/XS.xs:_PPI_Node__scope 0.903+
  94. sub scope { '' }
  95.  
  96. =pod
  97.  
  98. =head2 add_element $Element
  99.  
  100. The C<add_element> method adds a L<PPI::Element> object to the end of a
  101. C<PPI::Node>. Because Elements maintain links to their parent, an
  102. Element can only be added to a single Node.
  103.  
  104. Returns true if the L<PPI::Element> was added. Returns C<undef> if the
  105. Element was already within another Node, or the method is not passed 
  106. a L<PPI::Element> object.
  107.  
  108. =cut
  109.  
  110. sub add_element {
  111.     my $self = shift;
  112.  
  113.     # Check the element
  114.     my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
  115.     $_PARENT{refaddr $Element} and return undef;
  116.  
  117.     # Add the argument to the elements
  118.     push @{$self->{children}}, $Element;
  119.     Scalar::Util::weaken(
  120.         $_PARENT{refaddr $Element} = $self
  121.     );
  122.  
  123.     1;
  124. }
  125.  
  126. # In a typical run profile, add_element is the number 1 resource drain.
  127. # This is a highly optimised unsafe version, for internal use only.
  128. sub __add_element {
  129.     Scalar::Util::weaken(
  130.         $_PARENT{refaddr $_[1]} = $_[0]
  131.     );
  132.     push @{$_[0]->{children}}, $_[1];
  133. }
  134.  
  135. =pod
  136.  
  137. =head2 elements
  138.  
  139. The C<elements> method accesses all child elements B<structurally> within
  140. the C<PPI::Node> object. Note that in the base of the L<PPI::Structure>
  141. classes, this C<DOES> include the brace tokens at either end of the
  142. structure.
  143.  
  144. Returns a list of zero or more L<PPI::Element> objects.
  145.  
  146. Alternatively, if called in the scalar context, the C<elements> method
  147. returns a count of the number of elements.
  148.  
  149. =cut
  150.  
  151. sub elements {
  152.     if ( wantarray ) {
  153.         return @{$_[0]->{children}};
  154.     } else {
  155.         return scalar @{$_[0]->{children}};
  156.     }
  157. }
  158.  
  159. =pod
  160.  
  161. =head2 first_element
  162.  
  163. The C<first_element> method accesses the first element structurally within
  164. the C<PPI::Node> object. As for the C<elements> method, this does include
  165. the brace tokens for L<PPI::Structure> objects.
  166.  
  167. Returns a L<PPI::Element> object, or C<undef> if for some reason the
  168. C<PPI::Node> object does not contain any elements.
  169.  
  170. =cut
  171.  
  172. # Normally the first element is also the first child
  173. sub first_element {
  174.     $_[0]->{children}->[0];
  175. }
  176.  
  177. =pod
  178.  
  179. =head2 last_element
  180.  
  181. The C<last_element> method accesses the last element structurally within
  182. the C<PPI::Node> object. As for the C<elements> method, this does include
  183. the brace tokens for L<PPI::Structure> objects.
  184.  
  185. Returns a L<PPI::Element> object, or C<undef> if for some reason the
  186. C<PPI::Node> object does not contain any elements.
  187.  
  188. =cut
  189.  
  190. # Normally the last element is also the last child
  191. sub last_element {
  192.     $_[0]->{children}->[-1];
  193. }
  194.  
  195. =pod
  196.  
  197. =head2 children
  198.  
  199. The C<children> method accesses all child elements lexically within the
  200. C<PPI::Node> object. Note that in the case of the L<PPI::Structure>
  201. classes, this does B<NOT> include the brace tokens at either end of the
  202. structure.
  203.  
  204. Returns a list of zero of more L<PPI::Element> objects.
  205.  
  206. Alternatively, if called in the scalar context, the C<children> method
  207. returns a count of the number of lexical children.
  208.  
  209. =cut
  210.  
  211. # In the default case, this is the same as for the elements method
  212. sub children {
  213.     wantarray ? @{$_[0]->{children}} : scalar @{$_[0]->{children}};
  214. }
  215.  
  216. =pod
  217.  
  218. =head2 schildren
  219.  
  220. The C<schildren> method is really just a convenience, the significant-only
  221. variation of the normal C<children> method.
  222.  
  223. In list context, returns a list of significant children. In scalar context,
  224. returns the number of significant children.
  225.  
  226. =cut
  227.  
  228. sub schildren {
  229.     return grep { $_->significant } @{$_[0]->{children}} if wantarray;
  230.     my $count = 0;
  231.     foreach ( @{$_[0]->{children}} ) {
  232.         $count++ if $_->significant;
  233.     }
  234.     return $count;
  235. }
  236.  
  237. =pod
  238.  
  239. =head2 child $index
  240.  
  241. The C<child> method accesses a child L<PPI::Element> object by its
  242. position within the Node.
  243.  
  244. Returns a L<PPI::Element> object, or C<undef> if there is no child
  245. element at that node.
  246.  
  247. =cut
  248.  
  249. sub child {
  250.     $_[0]->{children}->[$_[1]];
  251. }
  252.  
  253. =pod
  254.  
  255. =head2 schild $index
  256.  
  257. The lexical structure of the Perl language ignores 'insignificant' items,
  258. such as whitespace and comments, while L<PPI> treats these items as valid
  259. tokens so that it can reassemble the file at any time. Because of this,
  260. in many situations there is a need to find an Element within a Node by
  261. index, only counting lexically significant Elements.
  262.  
  263. The C<schild> method returns a child Element by index, ignoring
  264. insignificant Elements. The index of a child Element is specified in the
  265. same way as for a normal array, with the first Element at index 0, and
  266. negative indexes used to identify a "from the end" position.
  267.  
  268. =cut
  269.  
  270. sub schild {
  271.     my $self = shift;
  272.     my $idx  = 0 + shift;
  273.     my $el   = $self->{children};
  274.     if ( $idx < 0 ) {
  275.         my $cursor = 0;
  276.         while ( exists $el->[--$cursor] ) {
  277.             return $el->[$cursor] if $el->[$cursor]->significant and ++$idx >= 0;
  278.         }
  279.     } else {
  280.         my $cursor = -1;
  281.         while ( exists $el->[++$cursor] ) {
  282.             return $el->[$cursor] if $el->[$cursor]->significant and --$idx < 0;
  283.         }
  284.     }
  285.     undef;
  286. }
  287.  
  288. =pod
  289.  
  290. =head2 contains $Element
  291.  
  292. The C<contains> method is used to determine if another L<PPI::Element>
  293. object is logically "within" a C<PPI::Node>. For the special case of the
  294. brace tokens at either side of a L<PPI::Structure> object, they are
  295. generally considered "within" a L<PPI::Structure> object, even if they are
  296. not actually in the elements for the L<PPI::Structure>.
  297.  
  298. Returns true if the L<PPI::Element> is within us, false if not, or C<undef>
  299. on error.
  300.  
  301. =cut
  302.  
  303. sub contains {
  304.     my $self    = shift;
  305.     my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
  306.  
  307.     # Iterate up the Element's parent chain until we either run out
  308.     # of parents, or get to ourself.
  309.     while ( $Element = $Element->parent ) {
  310.         return 1 if refaddr($self) == refaddr($Element);
  311.     }
  312.  
  313.     '';
  314. }
  315.  
  316. =pod
  317.  
  318. =head2 find $class | \&wanted
  319.  
  320. The C<find> method is used to search within a code tree for
  321. L<PPI::Element> objects that meet a particular condition.
  322.  
  323. To specify the condition, the method can be provided with either a simple
  324. class name (full or shortened), or a C<CODE>/function reference.
  325.  
  326.   # Find all single quotes in a Document (which is a Node)
  327.   $Document->find('PPI::Quote::Single');
  328.   
  329.   # The same thing with a shortened class name
  330.   $Document->find('Quote::Single');
  331.   
  332.   # Anything more elaborate, we so with the sub
  333.   $Document->find( sub {
  334.       # At the top level of the file...
  335.       $_[1]->parent == $_[0]
  336.       and (
  337.           # ...find all comments and POD
  338.           $_[1]->isa('PPI::Token::Pod')
  339.           or
  340.           $_[1]->isa('PPI::Token::Comment')
  341.       )
  342.   } );
  343.  
  344. The function will be passed two arguments, the top-level C<PPI::Node>
  345. you are searching in and the current L<PPI::Element> that the condition
  346. is testing.
  347.  
  348. The anonymous function should return one of three values. Returning true
  349. indicates a condition match, defined-false (C<0> or C<''>) indicates
  350. no-match, and C<undef> indicates no-match and no-descend.
  351.  
  352. In the last case, the tree walker will skip over anything below the
  353. C<undef>-returning element and move on to the next element at the same
  354. level.
  355.  
  356. To halt the entire search and return C<undef> immediately, a condition
  357. function should throw an exception (i.e. C<die>).
  358.  
  359. Note that this same wanted logic is used for all methods documented to
  360. have a C<\&wanted> parameter, as this one does.
  361.  
  362. The C<find> method returns a reference to an array of L<PPI::Element>
  363. objects that match the condition, false (but defined) if no Elements match
  364. the condition, or C<undef> if you provide a bad condition, or an error
  365. occurs during the search process.
  366.  
  367. In the case of a bad condition, a warning will be emitted as well.
  368.  
  369. =cut
  370.  
  371. sub find {
  372.     my $self   = shift;
  373.     my $wanted = $self->_wanted(shift) or return undef;
  374.  
  375.     # Use a queue based search, rather than a recursive one
  376.     my @found = ();
  377.     my @queue = @{$self->{children}};
  378.     eval {
  379.         while ( @queue ) {
  380.             my $Element = shift @queue;
  381.             my $rv      = &$wanted( $self, $Element );
  382.             push @found, $Element if $rv;
  383.  
  384.             # Support "don't descend on undef return"
  385.             next unless defined $rv;
  386.  
  387.             # Skip if the Element doesn't have any children
  388.             next unless $Element->isa('PPI::Node');
  389.  
  390.             # Depth-first keeps the queue size down and provides a
  391.             # better logical order.
  392.             if ( $Element->isa('PPI::Structure') ) {
  393.                 unshift @queue, $Element->finish if $Element->finish;
  394.                 unshift @queue, @{$Element->{children}};
  395.                 unshift @queue, $Element->start if $Element->start;
  396.             } else {
  397.                 unshift @queue, @{$Element->{children}};
  398.             }
  399.         }
  400.     };
  401.     if ( $@ ) {
  402.         # Caught exception thrown from the wanted function
  403.         return undef;
  404.     }
  405.  
  406.     @found ? \@found : '';
  407. }
  408.  
  409. =pod
  410.  
  411. =head2 find_first $class | \&wanted
  412.  
  413. If the normal C<find> method is like a grep, then C<find_first> is
  414. equivalent to the L<Scalar::Util> C<first> function.
  415.  
  416. Given an element class or a wanted function, it will search depth-first
  417. through a tree until it finds something that matches the condition,
  418. returning the first Element that it encounters.
  419.  
  420. See the C<find> method for details on the format of the search condition.
  421.  
  422. Returns the first L<PPI::Element> object that matches the condition, false
  423. if nothing matches the condition, or C<undef> if given an invalid condition,
  424. or an error occurs.
  425.  
  426. =cut
  427.  
  428. sub find_first {
  429.     my $self   = shift;
  430.     my $wanted = $self->_wanted(shift) or return undef;
  431.  
  432.     # Use the same queue-based search as for ->find
  433.     my @queue = @{$self->{children}};
  434.     my $rv    = eval {
  435.         # The defined() here prevents a ton of calls to PPI::Util::TRUE
  436.         while ( @queue ) {
  437.             my $Element = shift @queue;
  438.             my $rv      = &$wanted( $self, $Element );
  439.             return $Element if $rv;
  440.  
  441.             # Support "don't descend on undef return"
  442.             next unless defined $rv;
  443.  
  444.             # Skip if the Element doesn't have any children
  445.             next unless $Element->isa('PPI::Node');
  446.  
  447.             # Depth-first keeps the queue size down and provides a
  448.             # better logical order.
  449.             if ( $Element->isa('PPI::Structure') ) {
  450.                 unshift @queue, $Element->finish if defined($Element->finish);
  451.                 unshift @queue, @{$Element->{children}};
  452.                 unshift @queue, $Element->start  if defined($Element->start);
  453.             } else {
  454.                 unshift @queue, @{$Element->{children}};
  455.             }
  456.         }
  457.     };
  458.     if ( $@ ) {
  459.         # Caught exception thrown from the wanted function
  460.         return undef;
  461.     }
  462.  
  463.     $rv or '';
  464. }
  465.  
  466. =pod
  467.  
  468. =head2 find_any $class | \&wanted
  469.  
  470. The C<find_any> method is a short-circuiting true/false method that behaves
  471. like the normal C<find> method, but returns true as soon as it finds any
  472. Elements that match the search condition.
  473.  
  474. See the C<find> method for details on the format of the search condition.
  475.  
  476. Returns true if any Elements that match the condition can be found, false if
  477. not, or C<undef> if given an invalid condition, or an error occurs.
  478.  
  479. =cut
  480.  
  481. sub find_any {
  482.     my $self = shift;
  483.     my $rv   = $self->find_first(@_);
  484.     $rv ? 1 : $rv; # false or undef
  485. }
  486.  
  487. =pod
  488.  
  489. =head2 remove_child $Element
  490.  
  491. If passed a L<PPI::Element> object that is a direct child of the Node,
  492. the C<remove_element> method will remove the C<Element> intact, along
  493. with any of its children. As such, this method acts essentially as a
  494. 'cut' function.
  495.  
  496. If successful, returns the removed element.  Otherwise, returns C<undef>.
  497.  
  498. =cut
  499.  
  500. sub remove_child {
  501.     my $self  = shift;
  502.     my $child = _INSTANCE(shift, 'PPI::Element') or return undef;
  503.  
  504.     # Find the position of the child
  505.     my $key = refaddr $child;
  506.     my $p   = List::MoreUtils::firstidx {
  507.         refaddr $_ == $key
  508.     } @{$self->{children}};
  509.     return undef unless defined $p;
  510.  
  511.     # Splice it out, and remove the child's parent entry
  512.     splice( @{$self->{children}}, $p, 1 );
  513.     delete $_PARENT{refaddr $child};
  514.  
  515.     $child;
  516. }
  517.  
  518. =pod
  519.  
  520. =head2 prune $class | \&wanted
  521.  
  522. The C<prune> method is used to strip L<PPI::Element> objects out of a code
  523. tree. The argument is the same as for the C<find> method, either a class
  524. name, or an anonymous subroutine which returns true/false. Any Element
  525. that matches the class|wanted will be deleted from the code tree, along
  526. with any of its children.
  527.  
  528. The C<prune> method returns the number of C<Element> objects that matched
  529. and were removed, B<non-recursively>. This might also be zero, so avoid a
  530. simple true/false test on the return false of the C<prune> method. It
  531. returns C<undef> on error, which you probably B<should> test for.
  532.  
  533. =begin testing prune 2
  534.  
  535. # Avoids a bug in old Perls relating to the detection of scripts
  536. # Known to occur in ActivePerl 5.6.1 and at least one 5.6.2 install.
  537. my $hashbang = reverse 'lrep/nib/rsu/!#'; 
  538. my $document = PPI::Document->new( \<<"END_PERL" );
  539. $hashbang
  540.  
  541. use strict;
  542.  
  543. sub one { 1 }
  544. sub two { 2 }
  545. sub three { 3 }
  546.  
  547. print one;
  548. print "\n";
  549. print three;
  550. print "\n";
  551.  
  552. exit;
  553. END_PERL
  554.  
  555. isa_ok( $document, 'PPI::Document' );
  556. ok( defined($document->prune ('PPI::Statement::Sub')),
  557.     'Pruned multiple subs ok' );
  558.  
  559. =end testing
  560.  
  561. =cut
  562.  
  563. sub prune {
  564.     my $self   = shift;
  565.     my $wanted = $self->_wanted(shift) or return undef;
  566.  
  567.     # Use a depth-first queue search
  568.     my $pruned = 0;
  569.     my @queue  = $self->children;
  570.     eval {
  571.         while ( my $element = shift @queue ) {
  572.             my $rv = &$wanted( $self, $element );
  573.             if ( $rv ) {
  574.                 # Delete the child
  575.                 $element->delete or return undef;
  576.                 $pruned++;
  577.                 next;
  578.             }
  579.  
  580.             # Support the undef == "don't descend"
  581.             next unless defined $rv;
  582.  
  583.             if ( _INSTANCE($element, 'PPI::Node') ) {
  584.                 # Depth-first keeps the queue size down
  585.                 unshift @queue, $element->children;
  586.             }
  587.         }
  588.     };
  589.     if ( $@ ) {
  590.         # Caught exception thrown from the wanted function
  591.         return undef;        
  592.     }
  593.  
  594.     $pruned;
  595. }
  596.  
  597. # This method is likely to be very heavily used, to take
  598. # it slowly and carefuly.
  599. ### NOTE: Renaming this function or changing either to self will probably
  600. ###       break File::Find::Rule::PPI
  601. sub _wanted {
  602.     my $either = shift;
  603.     my $it     = defined($_[0]) ? shift : do {
  604.         Carp::carp('Undefined value passed as search condition') if $^W;
  605.         return undef;
  606.     };
  607.  
  608.     # Has the caller provided a wanted function directly
  609.     return $it if _CODELIKE($it);
  610.     if ( ref $it ) {
  611.         # No other ref types are supported
  612.         Carp::carp('Illegal non-CODE reference passed as search condition') if $^W;
  613.         return undef;
  614.     }
  615.  
  616.     # The first argument should be an Element class, possibly in shorthand
  617.     $it = "PPI::$it" unless substr($it, 0, 5) eq 'PPI::';
  618.     unless ( _CLASS($it) and $it->isa('PPI::Element') ) {
  619.         # We got something, but it isn't an element
  620.         Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
  621.         return undef;
  622.     }
  623.  
  624.     # Create the class part of the wanted function
  625.     my $wanted_class = "\n\treturn '' unless \$_[1]->isa('$it');";
  626.  
  627.     # Have we been given a second argument to check the content
  628.     my $wanted_content = '';
  629.     if ( defined $_[0] ) {
  630.         my $content = shift;
  631.         if ( ref $content eq 'Regexp' ) {
  632.             $content = "$content";
  633.         } elsif ( ref $content ) {
  634.             # No other ref types are supported
  635.             Carp::carp("Cannot create search condition for '$it': Not a PPI::Element") if $^W;
  636.             return undef;
  637.         } else {
  638.             $content = quotemeta $content;
  639.         }
  640.  
  641.         # Complete the content part of the wanted function
  642.         $wanted_content .= "\n\treturn '' unless defined \$_[1]->{content};";
  643.         $wanted_content .= "\n\treturn '' unless \$_[1]->{content} =~ /$content/;";
  644.     }
  645.  
  646.     # Create the complete wanted function
  647.     my $code = "sub {"
  648.         . $wanted_class
  649.         . $wanted_content
  650.         . "\n\t1;"
  651.         . "\n}";
  652.  
  653.     # Compile the wanted function
  654.     $code = eval $code;
  655.     (ref $code eq 'CODE') ? $code : undef;
  656. }
  657.  
  658.  
  659.  
  660.  
  661.  
  662. ####################################################################
  663. # PPI::Element overloaded methods
  664.  
  665. sub tokens {
  666.     map { $_->tokens } @{$_[0]->{children}};
  667. }
  668.  
  669. ### XS -> PPI/XS.xs:_PPI_Element__content 0.900+
  670. sub content {
  671.     join '', map { $_->content } @{$_[0]->{children}};
  672. }
  673.  
  674. # Clone as normal, but then go down and relink all the _PARENT entries
  675. sub clone {
  676.     my $self  = shift;
  677.     my $clone = $self->SUPER::clone;
  678.     $clone->__link_children;
  679.     $clone;
  680. }
  681.  
  682. sub location {
  683.     my $self  = shift;
  684.     my $first = $self->{children}->[0] or return undef;
  685.     $first->location;
  686. }
  687.  
  688.  
  689.  
  690.  
  691.  
  692. #####################################################################
  693. # Internal Methods
  694.  
  695. sub DESTROY {
  696.     local $_;
  697.     if ( $_[0]->{children} ) {
  698.         my @queue = $_[0];
  699.         while ( defined($_ = shift @queue) ) {
  700.             unshift @queue, @{delete $_->{children}} if $_->{children};
  701.  
  702.             # Remove all internal/private weird crosslinking so that
  703.             # the cascading DESTROY calls will get called properly.
  704.             %$_ = ();
  705.         }
  706.     }
  707.  
  708.     # Remove us from our parent node as normal
  709.     delete $_PARENT{refaddr $_[0]};
  710. }
  711.  
  712. # Find the position of a child
  713. sub __position {
  714.     my $key = refaddr $_[1];
  715.     List::MoreUtils::firstidx { refaddr $_ == $key } @{$_[0]->{children}};
  716. }
  717.  
  718. # Insert one or more elements before a child
  719. sub __insert_before_child {
  720.     my $self = shift;
  721.     my $key  = refaddr shift;
  722.     my $p    = List::MoreUtils::firstidx {
  723.              refaddr $_ == $key
  724.              } @{$self->{children}};
  725.     foreach ( @_ ) {
  726.         Scalar::Util::weaken(
  727.             $_PARENT{refaddr $_} = $self
  728.             );
  729.     }
  730.     splice( @{$self->{children}}, $p, 0, @_ );
  731.     1;
  732. }
  733.  
  734. # Insert one or more elements after a child
  735. sub __insert_after_child {
  736.     my $self = shift;
  737.     my $key  = refaddr shift;
  738.     my $p    = List::MoreUtils::firstidx {
  739.              refaddr $_ == $key
  740.              } @{$self->{children}};
  741.     foreach ( @_ ) {
  742.         Scalar::Util::weaken(
  743.             $_PARENT{refaddr $_} = $self
  744.             );
  745.     }
  746.     splice( @{$self->{children}}, $p + 1, 0, @_ );
  747.     1;
  748. }
  749.  
  750. # Replace a child
  751. sub __replace_child {
  752.     my $self = shift;
  753.     my $key  = refaddr shift;
  754.     my $p    = List::MoreUtils::firstidx {
  755.              refaddr $_ == $key
  756.              } @{$self->{children}};
  757.     foreach ( @_ ) {
  758.         Scalar::Util::weaken(
  759.             $_PARENT{refaddr $_} = $self
  760.             );
  761.     }
  762.     splice( @{$self->{children}}, $p, 1, @_ );
  763.     1;
  764. }
  765.  
  766. # Create PARENT links for an entire tree.
  767. # Used when cloning or thawing.
  768. sub __link_children {
  769.     my $self = shift;
  770.  
  771.     # Relink all our children ( depth first )
  772.     my @queue = ( $self );
  773.     while ( my $Node = shift @queue ) {
  774.         # Link our immediate children
  775.         foreach my $Element ( @{$Node->{children}} ) {
  776.             Scalar::Util::weaken(
  777.                 $_PARENT{refaddr($Element)} = $Node
  778.                 );
  779.             unshift @queue, $Element if $Element->isa('PPI::Node');
  780.         }
  781.  
  782.         # If it's a structure, relink the open/close braces
  783.         next unless $Node->isa('PPI::Structure');
  784.         Scalar::Util::weaken(
  785.             $_PARENT{refaddr($Node->start)}  = $Node
  786.             ) if $Node->start;
  787.         Scalar::Util::weaken(
  788.             $_PARENT{refaddr($Node->finish)} = $Node
  789.             ) if $Node->finish;
  790.     }
  791.  
  792.     1;
  793. }
  794.  
  795. 1;
  796.  
  797. =pod
  798.  
  799. =head1 TO DO
  800.  
  801. - Move as much as possible to L<PPI::XS>
  802.  
  803. =head1 SUPPORT
  804.  
  805. See the L<support section|PPI/SUPPORT> in the main module.
  806.  
  807. =head1 AUTHOR
  808.  
  809. Adam Kennedy E<lt>adamk@cpan.orgE<gt>
  810.  
  811. =head1 COPYRIGHT
  812.  
  813. Copyright 2001 - 2010 Adam Kennedy.
  814.  
  815. This program is free software; you can redistribute
  816. it and/or modify it under the same terms as Perl itself.
  817.  
  818. The full text of the license can be found in the
  819. LICENSE file included with this module.
  820.  
  821. =cut
  822.